package com.rrd.spring.event.router;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import com.rrd.spring.event.EventHandler;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * An {@link ApplicationListener} that can be used to register {@link Invoker}s for specific methods mapped to specific
 * {@link ApplicationEvent} types.
 * 
 * @see EventHandler
 * @author eugene_rachitskiy
 */
@SuppressWarnings("rawtypes")
public class EventRouter implements ApplicationListener{
    private final Map<Class<?>,List<Invoker>> invokerMap = new ConcurrentHashMap<Class<?>,List<Invoker>>(){
		private static final long serialVersionUID = 3533066198897028970L;
		@Override
        public List<Invoker> get(Object key) {
            List<Invoker> ret = super.get(key);
            if(ret!=null){
                return ret;
            }
            synchronized (this){
                ret = super.get(key);
                if(ret!=null){
                    return ret;
                }
                ret = new CopyOnWriteArrayList<Invoker>();
                this.put((Class<?>)key,ret);
                return ret;
            }
        }
    };
    public Map<Class<?>,List<Invoker>> getInvokerMap(){
        return invokerMap;
    }
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        for(Invoker invoker:invokerMap.get(applicationEvent.getClass())){
            invoker.invoke(applicationEvent);
        }
    }
}
